package com.zhaungjie.base.conduit;

import com.alibaba.fastjson.JSON;
import lombok.Data;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;


/**
 * 统一返回结果的类
 * 其中泛型<D>当前只起声明作用，当前还没用到它
 *
 * @author zhuangjie
 * @date 2023/11/16
 */
@Data
public class R implements Serializable {
    private static final long serialVersionUID=1L;

    /**
     * 可能会出现异常的Runnable
     *
     * @author zhuangjie
     * @date 2023/12/26
     */
    @FunctionalInterface
    public interface VolatileRunnable {
        void run() throws Throwable;
    }

    private Boolean success;
    private Integer code;
    private String message;
    private Object data;

    public<T> T getData(Class<T> clazz) {
        return JSON.parseObject(JSON.toJSONString(data), clazz);
    }
    // 为了隐藏普通的 getData 方法
    // private void getData() {}

    private R () {}


    /**
     * 完整成功响应自定义
     *
     * @param code    代码
     * @param message 消息
     * @return {@link R}
     */
    public static R ok(Integer code,String message) {
        R result = new R();
        result.setSuccess(true);
        result.setCode(code);
        result.setMessage(message);
        return result;
    }
    public static R ok(String message) {
        ResultCode resultCode = ResultCode.SUCCESS;
        return R.ok(resultCode.getCode(),message);
    }
    public static R ok() {
        ResultCode resultCode = ResultCode.SUCCESS;
        return R.ok(resultCode.getCode(),resultCode.getMessage());
    }


    public static R ok(ResultCode resultCode) {
        return R.ok(resultCode.getCode(),resultCode.getMessage());
    }



    public static R error(Integer code,String message) {
        R result = new R();
        result.setSuccess(false);
        result.setCode(code);
        result.setMessage(message);
        return result;
    }
    public static R error(String message) {
        ResultCode resultCode = ResultCode.FAIL;
        return error(resultCode.getCode(),message);
    }
    public static R error() {
        ResultCode resultCode = ResultCode.FAIL;
        return error(resultCode.getCode(),resultCode.getMessage());
    }
    public static R error(ResultCode codeEnum) {
        return error(codeEnum.getCode(),codeEnum.getMessage());
    }

    public static R auto(String taskName, Boolean isSuccess) {
        return (isSuccess != null && isSuccess)?R.ok(taskName+"成功！"):R.error(taskName+"失败！");
    }
    public static R auto(Boolean isSuccess) {
        return auto("操作",isSuccess);
    }

    /**
     * 需要非空响应数据
     * 应用于数据查询不出来时不抛出异常，而是返回null数据，但响应数据又不能是空数据的场景
     * @param data 数据
     * @return {@link R}
     */
    public static<T> R require(Class<T> clazz, T data ) {
        return data == null? R.error("获取数据失败！"):R.ok("获取数据成功！").data(data);
    }
    public static R require( Object data ) {
        return require(Object.class,data);
    }

    public<T> R data(Class<T> dataClazz, T data) {
        this.data = data;
        return this;
    }
    public<T> R data(T data) {
        return data(Object.class,data);
    }
    public R dataAsMap(Consumer<Map<String,Object>> consumer) {
        Map<String, Object> map = new HashMap<>(2);
        consumer.accept(map);
        return data(map);
    }
    public R message(String message) {
        this.message = message;
        return this;
    }

    public void response(HttpServletResponse response) {
        response.setHeader("content-type", "application/json;charset=UTF-8");
        response.setStatus(200);
        PrintWriter out = null;
        try {
            out = response.getWriter();
            String json = JSON.toJSONString(this);
            out.print(json);
            out.flush();
        } catch (IOException ignored) {} finally {
            if (out != null) {
                out.close();
            }
        }

    }
    public void response() {
        HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
        if (response == null) {
            throw new IllegalStateException("无法通过静态方式获取HttpServletResponse对象进行response!");
        }
        response(response);
    }

    /**
     * 捕获里面的异常，主要意义在于表面更语义、异常信息就是message的信息
     *
     * @param volatileRunnable 易挥发
     * @return {@link R}
     */
    public static R capture(VolatileRunnable volatileRunnable) {
        try {
            volatileRunnable.run();
        }catch (Throwable throwable) {
            return R.error(throwable.getMessage());
        }
        return R.ok();
    }

}


